<template>
  <el-dialog v-model="_value" title="图片裁剪" class="image-cropper" width="1000px">
    <div class="py-3">
      <img id="target-image" class="max-h-[500px] min-h-[200px]" :src="imgUrl" alt="" />
    </div>
    <template #footer>
      <div class="flex-center">
        <el-button @click="_value = false">取消</el-button>
        <el-button type="primary" @click="handleConfirm">确定</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'

defineOptions({
  name: 'Cropper',
})

const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false,
  },
  imgUrl: {
    type: String,
    default: '',
    required: true,
  },
  /** 裁剪比例 */
  ratio: {
    type: Number,
    default: 1,
  },
  /** 大小限制，单位Mb */
  limit: {
    type: Number,
    default: 20,
  },
})

const emit = defineEmits(['update:modelValue', 'confirm'])

const _value = useVModel(props, 'modelValue', emit)
const cropper = ref<null | Cropper>(null)
const cropperImageBase64 = ref('')

watch(_value, val => {
  if (val) {
    nextTick(() => {
      if (cropper.value) {
        cropper.value.destroy()
        cropper.value = null
      }
      cropper.value = new Cropper(document.getElementById('target-image') as HTMLImageElement, {
        viewMode: 1,
        dragMode: 'move',
        initialAspectRatio: 1,
        aspectRatio: props.ratio,
        background: true,
        zoomOnWheel: true,
        crop: e => {},
      })
    })
  }
})

const handleConfirm = () => {
  if (!cropper.value) return
  // 获取裁剪后的Canvas对象
  const croppedCanvas = cropper.value.getCroppedCanvas()
  // 设置最大宽度
  const maxWidth = 600

  // 计算调整后的尺寸
  let width = croppedCanvas.width
  let height = croppedCanvas.height

  if (width > maxWidth) {
    const ratio = maxWidth / width
    width *= ratio
    height *= ratio
  }

  // 创建一个新的Canvas元素
  const resizedCanvas = document.createElement('canvas')
  const resizedContext = resizedCanvas.getContext('2d')!

  // 设置新Canvas的尺寸
  resizedCanvas.width = width
  resizedCanvas.height = height

  // 将裁剪后的图像绘制到新Canvas中
  resizedContext.drawImage(croppedCanvas, 0, 0, width, height)
  cropperImageBase64.value = resizedContext.canvas.toDataURL('image/png', 0.9)
  const imageSize = calculateImageSize(cropperImageBase64.value) / 1024 / 1000

  if (imageSize > props.limit!) {
    ElMessage.error(`图片大小不能超过${imageSize}m`)
  } else {
    emit('confirm', cropperImageBase64.value as string)
  }

  _value.value = false
}

// 计算图片大小
const calculateImageSize = (dataURL: String) => {
  // 获取 Base64 编码部分
  const base64Part = dataURL.split(',')[1]
  // 计算 Base64 字符串的长度
  const base64Length = base64Part.length
  // Base64 编码后的长度是原始数据长度的 4/3 倍
  const imageSize = Math.round(base64Length * (3 / 4))
  return imageSize
}
</script>

<style lang="scss">
.image-cropper {
  padding: 0 !important;
}
</style>
